package net.kylewu.ui;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;

import net.kylewu.RCFFCommands;
import net.kylewu.RCFFProperties;

import org.dom4j.DocumentException;
import org.dyno.visual.swing.layouts.Bilateral;
import org.dyno.visual.swing.layouts.Constraints;
import org.dyno.visual.swing.layouts.GroupLayout;
import org.dyno.visual.swing.layouts.Leading;
import org.dyno.visual.swing.layouts.Trailing;

/**
 * 
 * @author Kyle Wu
 * 
 */
// VS4E -- DO NOT REMOVE THIS LINE!
public class OptionsDialog extends JDialog {

	private static final long serialVersionUID = 1L;

	private RCFFProperties rcffProperties;
	private RCFFCommands rcffCommands;
	private RCFFCommands changedRCFFCommands;

	private JTabbedPane jTabbedPane;
	private JButton jBtnApply;
	private JButton jBtnCancel;
	// Panel General
	private JPanel jPanelGeneral;
	private JLabel jLabel0;
	private JLabel jLabel1;
	private JLabel jLabel2;
	private JLabel jLabel3;
	private JLabel jLabel4;
	private JTextField jTextFieldUsername;
	private JPasswordField jPasswordField;
	private JSpinner jSpinnerInterval;
	private JCheckBox jCheckBoxAutostart;
	// Panel Commands
	private JScrollPane jScrollPaneCommands;
	private JTable jTableCommands;

	private static final String PREFERRED_LOOK_AND_FEEL = "javax.swing.plaf.metal.MetalLookAndFeel";

	public OptionsDialog(RCFFProperties rcffProperties,
			RCFFCommands rcffCommands) throws UnsupportedEncodingException,
			DocumentException {

		this.rcffProperties = rcffProperties;
		this.rcffCommands = rcffCommands;
		this.changedRCFFCommands = new RCFFCommands();
		initComponents();

	}

	private void initComponents() {
		setTitle("Options");
		setSize(300, 300);
		setFont(new Font("Dialog", Font.PLAIN, 12));
		setBackground(new Color(251, 251, 251));
		setForeground(Color.black);
		setLayout(new GroupLayout());
		add(getJBtnApply(), new Constraints(new Leading(12, 12, 12),
				new Trailing(12, 12, 12)));
		add(getJBtnCancel(), new Constraints(new Trailing(12, 102, 102),
				new Trailing(12, 12, 12)));
		add(getJTabbedPane(), new Constraints(new Bilateral(12, 12, 5),
				new Bilateral(12, 52, 7)));

	}

	private JScrollPane getJScrollPaneCommands() {
		if (jScrollPaneCommands == null) {
			jScrollPaneCommands = new JScrollPane();
			jScrollPaneCommands.setViewportView(getJTableCommands());
		}
		return jScrollPaneCommands;
	}

	private JTable getJTableCommands() {
		if (jTableCommands == null) {
			jTableCommands = new JTable();
			jTableCommands.setModel(new DefaultTableModel(rcffCommands
					.getData(), new String[] { "Remote Command",
					"System Command", }) {
				private static final long serialVersionUID = 1L;
				Class<?>[] types = new Class<?>[] { Object.class, Object.class, };

				public Class<?> getColumnClass(int columnIndex) {
					return types[columnIndex];
				}
			});
			jTableCommands
					.addPropertyChangeListener(new PropertyChangeListener() {

						@Override
						public void propertyChange(PropertyChangeEvent evt) {
							jTableCommandsPropertyChange(evt);
						}
					});
		}
		return jTableCommands;
	}

	private void jTableCommandsPropertyChange(PropertyChangeEvent evt) {
		int editingRow = ((JTable) evt.getSource()).getEditingRow();
		int editingColumn = ((JTable) evt.getSource()).getEditingColumn();

		if (editingRow != -1 && editingColumn != -1) {
			String oldCom = changedRCFFCommands.get(editingRow, editingColumn);
			String newCom = (String) ((JTable) evt.getSource()).getValueAt(
					editingRow, editingColumn);
			if (oldCom.compareTo(newCom) != 0) {
				if (editingColumn == 0
						&& changedRCFFCommands.getKeys().contains(oldCom)){
					JOptionPane.showMessageDialog(null,
							"There is a same command in this column.", "Error",
							JOptionPane.ERROR_MESSAGE);
					jTableCommands.setValueAt(oldCom, editingRow, editingColumn);
				}
				else
					changedRCFFCommands.edit(newCom, editingRow, editingColumn);
			}
		}
	}

	private JCheckBox getJCheckBoxAutostart() {
		if (jCheckBoxAutostart == null) {
			jCheckBoxAutostart = new JCheckBox();
			jCheckBoxAutostart.setText("yes");
			if (rcffProperties.isAutoStart())
				jCheckBoxAutostart.setSelected(true);
			else
				jCheckBoxAutostart.setSelected(false);
		}
		return jCheckBoxAutostart;
	}

	private JSpinner getJSpinnerInterval() {
		if (jSpinnerInterval == null) {
			jSpinnerInterval = new JSpinner();
			jSpinnerInterval.setModel(new SpinnerNumberModel());
			jSpinnerInterval.setValue(rcffProperties.getIntervalTime());
		}
		return jSpinnerInterval;
	}

	private JPasswordField getJTextFieldPassword() {
		if (jPasswordField == null) {
			jPasswordField = new JPasswordField();
			jPasswordField.setText(rcffProperties.getPassword());
		}
		return jPasswordField;
	}

	private JTextField getJTextFieldUsername() {
		if (jTextFieldUsername == null) {
			jTextFieldUsername = new JTextField();
			jTextFieldUsername.setText(rcffProperties.getUsername());
		}
		return jTextFieldUsername;
	}

	private JLabel getJLabel4() {
		if (jLabel4 == null) {
			jLabel4 = new JLabel();
			jLabel4.setText("seconds");
		}
		return jLabel4;
	}

	private JLabel getJLabel3() {
		if (jLabel3 == null) {
			jLabel3 = new JLabel();
			jLabel3.setText("autostart");
		}
		return jLabel3;
	}

	private JLabel getJLabel2() {
		if (jLabel2 == null) {
			jLabel2 = new JLabel();
			jLabel2.setText("interval");
		}
		return jLabel2;
	}

	private JLabel getJLabel1() {
		if (jLabel1 == null) {
			jLabel1 = new JLabel();
			jLabel1.setText("password");
		}
		return jLabel1;
	}

	private JLabel getJLabel0() {
		if (jLabel0 == null) {
			jLabel0 = new JLabel();
			jLabel0.setText("username");
		}
		return jLabel0;
	}

	private JPanel getJPanelGeneral() {
		if (jPanelGeneral == null) {
			jPanelGeneral = new JPanel();
			jPanelGeneral.setLayout(new GroupLayout());
			jPanelGeneral.add(getJTextFieldUsername(), new Constraints(
					new Leading(150, 101, 12, 12), new Leading(28, 12, 12)));
			jPanelGeneral.add(getJTextFieldPassword(), new Constraints(
					new Leading(150, 100, 12, 12), new Leading(68, 12, 12)));
			jPanelGeneral.add(getJLabel0(), new Constraints(new Leading(55, 10,
					10), new Leading(30, 12, 12)));
			jPanelGeneral.add(getJLabel1(), new Constraints(new Leading(52, 12,
					12), new Leading(70, 12, 12)));
			jPanelGeneral
					.add(getJSpinnerInterval(), new Constraints(new Leading(
							150, 40, 12, 12), new Leading(106, 27, 12, 12)));
			jPanelGeneral.add(getJLabel2(), new Constraints(new Leading(52, 12,
					12), new Leading(115, 12, 12)));
			jPanelGeneral.add(getJLabel4(), new Constraints(new Leading(202,
					12, 12), new Leading(115, 12, 12)));
			jPanelGeneral.add(getJLabel3(), new Constraints(new Leading(52, 12,
					12), new Leading(151, 12, 12)));
			jPanelGeneral.add(getJCheckBoxAutostart(), new Constraints(
					new Leading(150, 8, 8), new Leading(147, 8, 8)));
		}
		return jPanelGeneral;
	}

	private JTabbedPane getJTabbedPane() {
		if (jTabbedPane == null) {
			jTabbedPane = new JTabbedPane();
			jTabbedPane.addTab("General", getJPanelGeneral());
			jTabbedPane.addTab("Commands", getJScrollPaneCommands());
		}
		return jTabbedPane;
	}

	private JButton getJBtnCancel() {
		if (jBtnCancel == null) {
			jBtnCancel = new JButton();
			jBtnCancel.setText("Cancel");
			jBtnCancel.addActionListener(new ActionListener() {

				public void actionPerformed(ActionEvent event) {
					jBtnCancelActionActionPerformed(event);
				}
			});
		}
		return jBtnCancel;
	}

	private void jBtnCancelActionActionPerformed(ActionEvent event) {
		dispose();
	}

	private JButton getJBtnApply() {
		if (jBtnApply == null) {
			jBtnApply = new JButton();
			jBtnApply.setText("Apply");
			jBtnApply.addActionListener(new ActionListener() {

				public void actionPerformed(ActionEvent event) {
					try {
						jBtnApplyActionActionPerformed(event);
					} catch (DocumentException e) {
						JOptionPane.showMessageDialog(null,
								"Please check your property file.", "Error",
								JOptionPane.ERROR_MESSAGE);
					} catch (IOException e) {
						JOptionPane.showMessageDialog(null,
								"Please check your property file.", "Error",
								JOptionPane.ERROR_MESSAGE);
					}
				}
			});
		}
		return jBtnApply;
	}

	private void jBtnApplyActionActionPerformed(ActionEvent event)
			throws DocumentException, IOException {
		rcffProperties.setUsername(jTextFieldUsername.getText());
		rcffProperties
				.setPassword(String.valueOf(jPasswordField.getPassword()));
		rcffProperties.setIntervalTime((Integer) jSpinnerInterval.getValue());
		rcffProperties.setAutoStart(jCheckBoxAutostart.isSelected());
		rcffProperties.save();

		changedRCFFCommands.save();
		rcffCommands.copy(changedRCFFCommands);
	}

	private static void installLnF() {
		try {
			String lnfClassname = PREFERRED_LOOK_AND_FEEL;
			if (lnfClassname == null)
				lnfClassname = UIManager.getCrossPlatformLookAndFeelClassName();
			UIManager.setLookAndFeel(lnfClassname);
		} catch (Exception e) {
			System.err.println("Cannot install " + PREFERRED_LOOK_AND_FEEL
					+ " on this platform:" + e.getMessage());
		}
	}

	/**
	 * Main entry of the class. Note: This class is only created so that you can
	 * easily preview the result at runtime. It is not expected to be managed by
	 * the designer. You can modify it as you like.
	 */
	public static void main(String[] args) {
		installLnF();
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				RCFFProperties rcffProperties;
				RCFFCommands rcffCommands;
				try {
					rcffProperties = new RCFFProperties();
					rcffCommands = new RCFFCommands();
					OptionsDialog dialog = new OptionsDialog(rcffProperties,
							rcffCommands);
					dialog
							.setDefaultCloseOperation(OptionsDialog.DISPOSE_ON_CLOSE);
					// dialog.setTitle("OptionsDialog");
					// dialog.setLocationRelativeTo(null);
					// dialog.getContentPane().setPreferredSize(dialog.getSize());
					// dialog.pack();
					dialog.setVisible(true);
				} catch (DocumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		});
	}

}
